﻿//Written by Listings09 2011
using System;

namespace ForgeCraft
{
    public class ChestWindow : Window
    {
        private BlockPosition BlockPos;
        private Player _Player;

        public ChestWindow(BlockPosition bp) //Needed for server loading - DONT FULLY INITIALISE!
            : base(0, "Chest")
        {          
            slots = new InventoryItem[27];
            createdDate = DateTime.UtcNow;
            isPublic = true;
            allowedPlayers = "";
            ownerName = "";
            BlockPos = bp;
        }

        public ChestWindow(Player player, BlockPosition bp)
            : base(0, "Chest")
        {
            _Player = player;
            slots = new InventoryItem[27];
            createdDate = DateTime.UtcNow;
            isPublic = true;
            allowedPlayers = "";
            ownerName = player.name;

            for (int i = 0; i < slots.Length; ++i)
            {
                slots[i].Type = -1;
            }

            BlockPos = bp;

            player.currentWorld.WindowList.Add(bp, this);
        }

        override public void Close(Player player)
        {
            //TODO: This probably needs to be saved somewhere.
            player.currentWorld.WindowList[this.BlockPos] = this;
            _Viewers.Remove(player);

            //Save Players Inv
            this.Save(player);
        }

        override public void Remove(World world)
        {
            //Called when block is removed.
            foreach (InventoryItem i in slots)
            {
                if (i.Type > 0 && i.Count > 0)
                {
                    //Spawn Entities on top
                    new PickupEntity(BlockPos.x, BlockPos.y + 1, BlockPos.z, i, world, new Velocity(0, 0, 0));
                }
            }
        }

        override public bool Click(Player p, short slot, byte type, InventoryItem item)
        {
            Pair<bool, InventoryItem> TryAddResult;
            InventoryItem holding = p.WindowHolding;
            InventoryItem tempItem = holding;
            tempItem.Clear();

            if (slot < 0)
            {
                
                // outside window
               
                if (type == 1)
                {
                    p.WindowHolding.Count = 1;

                    if (p.WindowHolding.Count == 1)
                    {
                        p.WindowHolding.Clear();
                    }
                    else
                    {
                        holding.Count--;
                        if (!item.Equals(slots[slot])) return false;
                        p.SetHolding(slots[slot]);
                        SetSlot(slot, item);
                    }

                    tempItem = holding;
                    tempItem.Count = 1;
                    
                    BlockPosition spawnPos = p.GetFacingCoord();
                    new PickupEntity(spawnPos.x, spawnPos.y, spawnPos.z, tempItem, p.currentWorld, new Velocity(0, 0, 0));
                }
                else
                {
                    p.WindowHolding.Clear();

                    BlockPosition spawnPos = p.GetFacingCoord();
                    new PickupEntity(spawnPos.x, spawnPos.y, spawnPos.z, holding, p.currentWorld, new Velocity(0, 0, 0));
                }
                return true;
            }
            else if (slot >= slots.Length) //Using their inventory
            {
                slot = (short)(slot - 18);

                if (holding.Type > 0) //Held item Click
                {
                    if (type == 0) //Normal click
                    {
                        if (!holding.Type.Equals(p.Inventory.slots[slot].Type))
                        {
                            p.SetHolding(p.Inventory.slots[slot]);
                            p.Inventory.SetSlot(slot, holding);
                            return true;
                        }
                        TryAddResult = p.Inventory.TryAddItem(slot, holding);
                        if (TryAddResult.First)
                        {
                            holding.Clear();
                            p.SetHolding(holding);
                        }
                        else
                        {
                            p.SetHolding(TryAddResult.Second);
                        }
                    }
                    else //Player has right-clicked
                    {
                        if (!holding.Type.Equals(p.Inventory.slots[slot].Type) && p.Inventory.slots[slot].Type > 0)
                        {
                            p.SetHolding(p.Inventory.slots[slot]);
                            p.Inventory.SetSlot(slot, holding);
                            return true;
                        }
                        InventoryItem singleItem = holding;

                        singleItem.Count = 1;

                        TryAddResult = p.Inventory.TryAddItem(slot, singleItem);

                        if (TryAddResult.First)
                        {
                            holding = PopItem(holding);
                            p.SetHolding(holding);
                        }
                        else
                        {
                            p.SetHolding(TryAddResult.Second);
                        }
                    }
                    return true;
                }
                else //Unheld Inv Click
                {
                    if (type == 0) //Normal click
                    {
                        if (item.Equals(p.Inventory.slots[slot]))
                        {
                            p.SetHolding(p.Inventory.slots[slot]);
                            p.Inventory.SetSlot(slot, holding);
                        }
                        else //Set them down in a slot
                        {
                            if (!holding.Equals(p.Inventory.slots[slot])) return false;
                            TryAddResult = p.Inventory.TryAddItem(slot, item);
                            if (TryAddResult.First)
                            {
                                holding.Clear();
                                p.SetHolding(holding);
                            }
                            else
                            {
                                p.SetHolding(TryAddResult.Second);
                            }
                        }
                    }
                    else //Player has right-clicked
                    {
                        if (item.Count > 1)
                        {
                            int items = Math.Abs(item.Count / 2);
                            int remainder = Math.Abs(item.Count % 2);

                            tempItem = item;
                            item.Count = (byte)items;
                            tempItem.Count = (byte)(items + remainder);
                            SetSlot(slot, item);
                            p.SetHolding(tempItem);
                        }
                        else
                        {
                            p.SetHolding(item);
                            item.Clear();
                            SetSlot(slot, item);
                        }
                    }
                    return true;
                }
            }
            else //Player is using the chest
            {
                if (holding.Type > 0) //Held item Click
                {
                    if (type == 0) //Normal click
                    {
                        if (!holding.Type.Equals(slots[slot].Type))
                        {
                            p.SetHolding(slots[slot]);
                            SetSlot(slot, holding);
                            return true;
                        }
                        TryAddResult = TryAddItem(slot, holding);
                        if (TryAddResult.First)
                        {
                            holding.Clear();
                            p.SetHolding(holding);
                        }
                        else
                        {
                            p.SetHolding(TryAddResult.Second);
                        }
                    }
                    else //Player has right-clicked
                    {
                        if (!holding.Type.Equals(slots[slot].Type) && slots[slot].Type > 0)
                        {
                            p.SetHolding(slots[slot]);
                            SetSlot(slot, holding);
                            return true;
                        }
                        InventoryItem singleItem = holding;

                        singleItem.Count = 1;

                        TryAddResult = TryAddItem(slot, singleItem);

                        if (TryAddResult.First)
                        {
                            p.SetHolding(PopItem(holding));
                        }
                        else
                        {
                            p.SetHolding(TryAddResult.Second);
                        }
                    }
                    return true;
                }
                else //Unheld Inv Click
                {
                    if (type == 0) //Normal click
                    {
                        if (item.Equals(slots[slot]))
                        {
                            p.SetHolding(slots[slot]);
                            SetSlot(slot, holding);
                        }
                        else //Set them down in a slot
                        {
                            if (!holding.Equals(slots[slot])) return false;
                            TryAddResult = TryAddItem(slot, item);
                            if (TryAddResult.First)
                            {
                                holding.Clear();
                                p.SetHolding(holding);
                            }
                            else
                            {
                                p.SetHolding(TryAddResult.Second);
                            }
                        }
                    }
                    else //Player has right-clicked
                    {
                        //if (item.Count == 1) return false;
                        if (item.Type > 0) //Player has split a stack.
                        {
                            if (item.Count > 1)
                            {
                                int items = Math.Abs(item.Count / 2);
                                int remainder = Math.Abs(item.Count % 2);

                                tempItem = item;
                                item.Count = (byte)items;
                                tempItem.Count = (byte)(items + remainder);
                                SetSlot(slot, item);
                                p.SetHolding(tempItem);
                            }
                            else
                            {
                                p.SetHolding(item);
                                item.Clear();
                                SetSlot(slot, item);
                            }
                        }
                        else
                        {
                            if (!item.Equals(slots[slot])) return false;

                            InventoryItem singleItem = holding;

                            singleItem.Count = 1;

                            TryAddResult = TryAddItem(slot, singleItem);

                            if (TryAddResult.First)
                            {
                                p.SetHolding(PopItem(holding));
                            }
                            else
                            {
                                p.SetHolding(TryAddResult.Second);
                            }
                        }
                    }
                    return true;
                }
            }
        }
    }
}
